package org.antlr.runtime.misc;

import java.util.Enumeration;
import java.util.Hashtable;
import java.util.Vector;

/**
 * Sometimes we need to map a key to a value but key is two pieces of data. This
 * nested hash table saves creating a single key each time we access map; avoids
 * mem creation.
 */
public class DoubleKeyMap {
	Hashtable data = new Hashtable();

	public Object put(Object k1, Object k2, Object v) {
		Hashtable data2 = (Hashtable) data.get(k1);
		Object prev = null;
		if (data2 == null) {
			data2 = new Hashtable();
			data.put(k1, data2);
		} else {
			prev = data2.get(k2);
		}
		data2.put(k2, v);
		return prev;
	}

	public Object get(Object k1, Object k2) {
		Hashtable data2 = (Hashtable) data.get(k1);
		if (data2 == null)
			return null;
		return data2.get(k2);
	}

	public Hashtable get(Object k1) {
		return (Hashtable) data.get(k1);
	}

	/** Get all values associated with primary key */
	public Vector values(Object k1) {
		Hashtable data2 = (Hashtable) data.get(k1);
		if (data2 == null)
			return null;
		Enumeration values = data2.elements();
		Vector v = new Vector();
		while (values.hasMoreElements()) {
			v.addElement(values.nextElement());
		}
		return v;
	}

	/** get all primary keys */
	public Vector keySet() {
		Enumeration keys = data.keys();
		Vector v = new Vector();
		while (keys.hasMoreElements()) {
			v.addElement(keys.nextElement());
		}
		return v;
	}

	/** get all secondary keys associated with a primary key */
	public Vector keySet(Object k1) {
		Hashtable data2 = (Hashtable) data.get(k1);
		if (data2 == null)
			return null;
		Enumeration keys = data2.keys();
		Vector v = new Vector();
		while (keys.hasMoreElements()) {
			v.addElement(keys.nextElement());
		}
		return v;
	}

	public Vector values() {
		Vector s = new Vector();
		Enumeration values = data.elements();
		while (values.hasMoreElements()) {
			Hashtable k2 = (Hashtable) values.nextElement();
			Enumeration values2 = k2.elements();
			while (values2.hasMoreElements()) {
				s.addElement(values2.nextElement());
			}
		}
		return s;
	}
}
